﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using Leffaetsin.Controllers;
using Leffaetsin.Models;
using Leffaetsin.Services.Providers.ShowProviders;
using RestSharp;

namespace Leffaetsin.Services.Providers.IMDBProviders
{
    public static class ImdbApiProvider
    {
        public static void FillImdbData(Movie movie)
        {
            if (movie.Title == null)
                return;

            // TODO: kutsu movieproxycontrolleria tässä! + lisää sille cache..
            var imdbDto = GetMovieDataFromImdb(movie.OriginalTitle.StripForApi(), movie.ProductionYear);
            

            if (imdbDto == null) return;

            movie.ImdbId = imdbDto.imdb_id;
            movie.ImdbLink = imdbDto.imdb_url;
            movie.ApiUrl = imdbDto.ApiUrl;
            movie.Rating = imdbDto.rating;
            movie.Genres = imdbDto.genres;

            if (String.IsNullOrEmpty(movie.ThumbNailUrl))
                movie.ThumbNailUrl = imdbDto.poster;

            // worst case - fetch from Finnkino
            if (String.IsNullOrEmpty(movie.ThumbNailUrl)) {
                var finnkinoProvider = new FinnkinoProvider();
                var finnkinoMovie = finnkinoProvider.GetShows(movie.AreaName).FirstOrDefault(e => e.OriginalTitle == movie.OriginalTitle);
                if (finnkinoMovie != null)
                    movie.ThumbNailUrl = finnkinoMovie.EventSmallImagePortrait; 
            }
        }

        
        // TODO: tällanen cache myös Areoille ja FinnkinoDatalle!
        private static item GetMovieDataFromImdb(string title, string year)
        {
            ObjectCache cache = MemoryCache.Default;;
            
            var cachedMovie = cache.Get(title) as item;

            if (cachedMovie == null || String.IsNullOrEmpty(cachedMovie.rating))
            {
                cachedMovie = GetImdbApiMovie(title, year);
                if (cachedMovie == null)
                    return null;

                var policy = new CacheItemPolicy();
                policy.AbsoluteExpiration = DateTimeOffset.Now.AddHours(10);
                cache.Set(title, cachedMovie, policy);
            }

            return cachedMovie;

            /*
            item cachedMovie;
            MoviesCache.TryGetValue(title, out cachedMovie);

            if (cachedMovie == null || String.IsNullOrEmpty(cachedMovie.rating))
            {
                cachedMovie = MoviesCache[title] = GetImdbApiMovie(title, year);
            }
            return cachedMovie;
             * */
        }
        public static item GetImdbApiMovie(string title, string year, bool acceptNull = false)
        {
            if (!String.IsNullOrEmpty(year))
                year = "&yg=1&year=" + year;

            var client = new RestClient("http://imdbapi.org/");
            var request = new RestRequest("?q=" + title + "&type=xml&mt=T&plot=simple&episode=0&limit=5&lang=en-US" + year, Method.GET);

            var obj = client.Execute<Movies>(request);

            if (obj.Data == null)
                return null;

            obj.Data.IMDBDocumentList.ForEach(i => i.ApiUrl = client.BuildUri(request).ToString());

            var movie = obj.Data.IMDBDocumentList.FirstOrDefault(m => string.Equals(m.title, title, StringComparison.CurrentCultureIgnoreCase));

            if (movie == null && !acceptNull)
                return GetImdbApiMovie(title, String.Empty, true);

            if (movie == null && Regex.IsMatch(title, ".*\\d.*"))
                movie = obj.Data.IMDBDocumentList.SingleOrDefault(m => m.title.ToLowerInvariant().Contains(title.ToLowerInvariant() + ":"));

            if (movie == null && Regex.IsMatch(title, ".*\\d.*"))
                movie = obj.Data.IMDBDocumentList.SingleOrDefault(m => m.title.ToLowerInvariant().Contains(title.ToLowerInvariant()) && m.type == "M");

            if (movie == null)
                movie = obj.Data.IMDBDocumentList.FirstOrDefault(m => m.type == "M");

            return movie;
        }
    }

    public static class StringExtensions
    {
        public static string StripForApi(this string str)
        {
            
            
            var replaceWithEmptys = new List<string>()
                                       {
                                           "NV12:", // ehe
                                           "HFR",
                                            " - (3D)",
                                            " - 3D",
                                            "3D",
                                            " - (2D)",
                                            " - 2D",
                                            "2D",
                                        };

            var replaceWiths = new Dictionary<string, string>();
            // hehe
            replaceWiths.Add("3Simoa", "3 Simoa");

            foreach (var replaceWithEmpty in replaceWithEmptys)
            {
                str = str.Replace(replaceWithEmpty, "");
            }

            foreach (var replaceWith in replaceWiths)
            {
                str = str.Replace(replaceWith.Key, replaceWith.Value);
            }

            // "Movie Name (suom. puh.) (2D)" ==> "Movie Name"
            Regex replace = new Regex(@"\(.*\)");
            str = replace.Replace(str, "");
            
            return str.Trim().ToLowerInvariant();
        }
    }
}